/*
 * File:   StreamSurface.cpp
 * Author: mvdr
 *
 * Created on January 30, 2013, 7:24 PM
 */

#include "StreamSurface.h"
#include "GL/gl.h"
#include <iostream>

using namespace std;


StreamSurface::StreamSurface()
:
    d_segments(100),
    d_setting(true)
{
    d_scale = 0.25;
    d_uses_vector_dataset = true;
    d_name = "Stream surfaces (BETA)";
}

void StreamSurface::draw(float winW, float winH, int t, int slices, int sliceDT)
{
    if (not d_setting && t < slices - 1)
    {
        const int DIM = d_simulation->getDim();
        fftw_real  wn = (fftw_real)winW / (fftw_real)(DIM + 1);  // Grid cell width
        fftw_real  hn = (fftw_real)winH / (fftw_real)(DIM + 1);  // Grid cell heigh        
       
        float thisX = interpolate(d_x1, d_x2, t / sliceDT);
        float thisY = interpolate(d_y1, d_y2, t / sliceDT);
        float thatX = interpolate(d_x1, d_x2, t / sliceDT + 1);
        float thatY = interpolate(d_y1, d_y2, t / sliceDT + 1);
       
        Vector2f thisCurPos (thisX, thisY);
        Vector2f thatCurPos (thatX, thatY);
       
       
        for (int i = 0; i < d_segments; ++i)
        {
            Vector2f thisV = d_vector_dataset->getData(
                    thisCurPos.x, thisCurPos.y, t);
            Vector2f thatV = d_vector_dataset->getData(
                    thatCurPos.x, thatCurPos.y, t + sliceDT);
           
            if (thisV.length() > 0)
                thisV.normalize();
           
            if (thatV.length() > 0)
                thatV.normalize();
           
            Vector2f thisNewPos = thisCurPos + thisV * d_scale;
            Vector2f thatNewPos = thatCurPos + thatV * d_scale;
           
            outOfBounds(thisNewPos);
            outOfBounds(thatNewPos);
            
            
            if (not (thisCurPos.x == thisNewPos.x && 
                    thisCurPos.y == thisNewPos.y &&
                    thatCurPos.x == thatNewPos.x &&
                    thatCurPos.y == thatNewPos.y)) 
            {
                                
                glBegin(GL_QUADS);            
                setGLColor(thisCurPos.x, thisCurPos.y, t);
                glVertex3f(wn + thisCurPos.x * wn, hn + thisCurPos.y * hn, 0.0);
                setGLColor(thisNewPos.x, thisNewPos.y, t);
                glVertex3f(wn + thisNewPos.x * wn, hn + thisNewPos.y * hn, 0.0);
                setGLColor(thatNewPos.x, thatNewPos.y, t + sliceDT);
                glVertex3f(wn + thatNewPos.x * wn, hn + thatNewPos.y * hn, -d_dh);
                setGLColor(thatCurPos.x, thatCurPos.y, t + sliceDT);
                glVertex3f(wn + thatCurPos.x * wn, hn + thatCurPos.y * hn, -d_dh);
                glEnd();
            }
           
            thisCurPos = thisNewPos;
            thatCurPos = thatNewPos;            
        }
    }
   
}

void StreamSurface::addBegin(float x, float y, int t)
{
    d_setting = true;
    d_x1 = x;
    d_y1 = y;
    d_t1 = t;
}

void StreamSurface::addEnd(float x, float y, int t)
{
    d_x2 = x;
    d_y2 = y;
    d_t2 = t;
    d_setting = false;
    }

float StreamSurface::interpolate(float v1, float v2, int t)
{
    float w2 = float(t - d_t1) / (d_t2 - d_t1);
    return (1 - w2) * v1 + w2 * v2;
}

bool StreamSurface::outOfBounds(Vector2f &v)
{

    float dim = d_simulation->getDim();    
    bool retVal;
   
    if (v.x < 0.0)
    {
        v.x = 0.0;
        retVal = true;                
    }
   
    if (v.y < 0.0)
    {
        v.y = 0.0;
        retVal = true;                
    }
   
    if (v.x > dim)
    {
        v.x = dim;
        retVal = true;
    }
   
    if (v.y > dim)
    {
        v.y = dim;
        retVal = true;
    }    
   
    return retVal;
}

